package interpreter;

import interpreter.debugger.DebugCodeTable;
import interpreter.debugger.DebugVirtualMachine;
import java.io.*;

/*
 * Interpreter class runs the interpreter
 * <ol>
 * <li>Perform all initializations</li>
 * <li>Load the bytecodes from file</li>
 * <li>Run the virtual machine</li>
 * </ol>
 */

public class Interpreter {
    boolean debugmode;
    ByteCodeLoader bcl;

    /**
     * Constructor initializes the byte code table, loads
     * the file of byte codes and handles any exceptions
     *
     * @param args command line arguments (should be either 1 or 2)
     */
    public Interpreter( String[] args ) {
        debugmode = false;
        String codeFile;
        if( args.length == 2 && args[0].equalsIgnoreCase("-d") ) { // Switch
            debugmode = true;
            codeFile = args[1];
        } else codeFile = args[0];

        // Opens up file
        try {
            bcl = new ByteCodeLoader(codeFile, debugmode);
        } catch( FileNotFoundException fnf ) {
            System.out.println("File not found - try again!");
        } catch( IOException io ) {
            System.out.println("IOException: "+ io.getMessage());
        }
    }

    /**
     * Loads up the byte codes and starts the appropriate virtual machine. Finally 
     * the virtual machine executes the program.
     */
    void run() {
        VirtualMachine vm;
        Program program = bcl.loadCodes();

        // Opens up the virtual machine (debug or not)
        if( debugmode ) vm = new DebugVirtualMachine( program );
        else vm = new VirtualMachine( program );

        // Executes program (depending on mode)
        vm.executeProgram();
    }

    /**
     * The starting point of the Interpreter. Checks for the correct amount of
     * arguments, then instantiates itself and calls the run() method
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        if( args.length == 0 ) {
            System.out.println("Incorrect usage, try: java interpreter.Interpreter <file> [-d]");
            System.exit(-1);
        }
        (new Interpreter( args )).run();
    }

}
